package com.xjh.serverinspect.security;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.io.Encoders;
import io.jsonwebtoken.security.SignatureException;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.spec.SecretKeySpec;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * JWT工具类
 * </p>
 *
 * @author xujinghui
 * @since 2024-12-11
 */
@Slf4j
public final class JWTUtils {
    private static final String issuer = "server-inspect";

    private JWTUtils() {
    }

    /**
     * 创建token
     *
     * @param claims 声明
     * @param secret 秘钥
     * @param millis 过期时间(毫秒)
     * @return String
     */
    public static String create(Map<String, Object> claims, String secret, long millis) {
        SecretKeySpec key = new SecretKeySpec(Decoders.BASE64.decode(secret), "HmacSHA256");
        Date now = new Date();
        Date expiration = new Date(now.getTime() + millis);
        return Jwts.builder().issuer(issuer).issuedAt(now).expiration(expiration).claims(claims).signWith(key).compact();
    }

    /**
     * 验证token
     *
     * @param token  token
     * @param secret 秘钥
     * @return boolean
     */
    public static boolean verify(String token, String secret) {
        SecretKeySpec key = new SecretKeySpec(Decoders.BASE64.decode(secret), "HmacSHA256");
        return Jwts.parser().verifyWith(key).build().parseSignedClaims(token) != null;
    }

    /**
     * 解析token
     *
     * @param token  token
     * @param secret 秘钥
     * @return Map<String, Object>
     */
    public static Map<String, Object> parse(String token, String secret) {
        SecretKeySpec key = new SecretKeySpec(Decoders.BASE64.decode(secret), "HmacSHA256");
        return Jwts.parser().verifyWith(key).build().parseSignedClaims(token).getPayload();
    }

    /**
     * 静默解析token（返回异常信息，不抛出异常）
     *
     * @param token  token
     * @param secret 秘钥
     * @return Map<String, Object> {"success": boolean, "payload": Map<String, Object>, "message": String}
     */
    public static Map<String, Object> silentParse(String token, String secret) {
        Map<String, Object> result = new HashMap<>();
        result.put("success", false);
        SecretKeySpec key = new SecretKeySpec(Decoders.BASE64.decode(secret), "HmacSHA256");
        try {
            Claims payload = Jwts.parser().verifyWith(key).build().parseSignedClaims(token).getPayload();
            result.put("payload", payload);
            result.put("success", true);
        } catch (ExpiredJwtException e) {
            result.put("message", "token已过期");
            log.error("token已过期: {}", token, e);
        } catch (SignatureException e) {
            result.put("message", "无效签名");
            log.error("无效签名: {}", token, e);
        } catch (JwtException e) {
            result.put("message", "无效token");
            log.error("无效token: {}", token, e);
        } catch (Exception e) {
            result.put("message", "解析token失败");
            log.error("解析token失败: {}", token, e);
        }
        return result;
    }

    /**
     * 生成随机秘钥
     *
     * @return String
     */
    public static String randomSecret() {
        return Encoders.BASE64.encode(Jwts.SIG.HS256.key().build().getEncoded());
    }

}